package service

import (
	"encoding/json"
	"errors"
	"reflect"
	"strconv"

	"gorm.io/gorm"

	"collecter/app/cache"
	"collecter/app/common/enum"
	"collecter/app/common/helper"
	"collecter/app/lang"
	"collecter/app/model"
)

type TreeType struct {
	Id       int64       `json:"id"`
	Pid      int64       `json:"pid"`
	CateName string      `json:"cate_name"`
	Icon     string      `json:"icon"`
	SubList  []*TreeType `json:"sub_list"`
}

type CategoryService struct {
	Id       int64  `json:"id,omitempty"`
	UserId   int64  `json:"user_id,omitempty"`
	Pid      int64  `json:"pid,omitempty"`
	CateName string `json:"cate_name,omitempty"`
	Icon     string `json:"icon,omitempty"`
	Sort     int    `json:"sort,omitempty"`
}

var Trees = make([]TreeType, 0, 0)

func NewCategory(userId int64) *CategoryService {
	return &CategoryService{UserId: userId}
}

// TreeList
//
//	@Description: 获取分类树形列表
//	@receiver cs 分类的 model 对象实例，必须包含 UserId 的值
//	@return []*TreeType
//	@return error
func (cs *CategoryService) TreeList() ([]TreeType, error) {
	var list = make([]*model.Categorys, 0, 0)
	var tree TreeType
	if cs.UserId == 0 {
		return Trees, errors.New("参数错误")
	}
	cacheKey := enum.USER_CATEGORY_TREE + strconv.FormatInt(cs.UserId, 10)
	if err := cache.Cacher.Has(cacheKey); err == nil {
		if listByte, err := cache.Cacher.Get(cacheKey); err != nil {
			return Trees, err
		} else if len(listByte) > 0 {
			if err := json.Unmarshal(listByte, &Trees); err != nil {
				return Trees, err
			}
			return Trees, nil
		}
	}
	if err := helper.Db.Where(&cs).Where("status = 1").Order("sort asc").Find(&list).Error; err != nil {
		return Trees, nil
	}
	for _, val := range list {
		tree.Id = val.Id
		tree.Pid = val.Pid
		tree.CateName = val.CateName
		tree.Icon = val.Icon
		Trees = append(Trees, tree)
	}
	if val, err := makeCateTree(Trees); err != nil {
		return Trees, err
	} else {
		Trees = val
	}
	var treeJson []byte
	if val, err := json.Marshal(Trees); err != nil {
		return Trees, err
	} else {
		treeJson = val
	}
	if err := cache.Cacher.Set(cacheKey, treeJson, 0); err != nil {
		return Trees, err
	}
	return Trees, nil
}

func (cs *CategoryService) Create() error {
	if cs.UserId == 0 {
		return errors.New("参数错误")
	}
	if len(cs.CateName) == 0 {
		cs.CateName = "默认"
	}
	if cs.Sort == 0 {
		cs.Sort = 1
	}
	var category model.Categorys
	category.UserId = cs.UserId
	category.CateName = cs.CateName
	if err := helper.Db.Where(&category).First(&category).Error; err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			return err
		}
	} else {
		return errors.New("分类已经存在")
	}
	category.Pid = cs.Pid
	category.Sort = cs.Sort
	category.Status = enum.STATUS_ENABLED
	if err := helper.Db.Create(&category).Error; err != nil {
		return err
	}
	return nil
}

func (cs *CategoryService) Update(id int64) error {
	var category model.Categorys
	category.Id = id
	if err := helper.Db.Where(&category).First(&category).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return errors.New("分类不存在")
		}
		return err
	}
	if helper.Db.Where("cate_name = ? and status != ?", cs.CateName, enum.STATUS_DELETE).First(&model.Categorys{}).Error == nil {
		return errors.New("分类已经存在")
	}
	category.CateName = cs.CateName
	category.Pid = cs.Pid
	category.Sort = cs.Sort
	category.Icon = cs.Icon
	if err := helper.Db.Updates(&category).Error; err != nil {
		return err
	}
	return nil
}

/*
 *  UserDefaultCategory
 * @Description: 查询用户的默认分类
 * @receiver cs 分类的 model 对象实例，必须包含 UserId 的值
 * @return CategoryService
 * @return error
*/
func (cs *CategoryService) UserDefaultCategory() (*model.Categorys, error) {
	var serv *model.Categorys
	if cs.UserId == 0 {
		return serv, errors.New(lang.CodeMessage(6))
	}
	cs.CateName = "默认"
	if err := helper.Db.Where(&serv).First(&serv).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return serv, errors.New("分类不存在")
		}
		return serv,err
	}
	return serv, nil
}

/**
*  makeCateTree
*  @Description: 生成树结构
*  @param nodes
*  @return error
*  @return []*CTreeType
 */
func makeCateTree(cates []TreeType) ([]TreeType, error) {
	for key, val := range cates {
		rst := findCateChild(val.Id, cates)
		if len(rst) > 0 {
			for k, _ := range rst {
				cates[key].SubList = append(cates[key].SubList, &rst[k])
			}
			_, _ = makeCateTree(rst)
		}
	}
	var treeNodes []TreeType
	// 找出 pid = 0 的节点
	for key, val := range cates {
		if val.Pid == 0 {
			treeNodes = append(treeNodes, cates[key])
		}
	}
	return treeNodes, nil
}

/**
*  findCateChild
*  @Description: 寻找下级
*  @param nodeId 当前节点 id
*  @param allNodes 所有节点列表
*  @return []*CTreeType 找到的所有下级列表
 */
func findCateChild(cateId int64, allCates []TreeType) []TreeType {
	children := make([]TreeType, 0, 0)
	if cateId <= 0 || !reflect.ValueOf(allCates).IsValid() {
		return children
	}
	for key, val := range allCates {
		if val.Pid == cateId {
			children = append(children, allCates[key])
		}
	}
	return children
}
